/*-----------------------------------------------------------------------------------*/
/* Nuvoton Corporation confidential                                                  */
/*                                                                                   */
/* Copyright (c) 2009 by Nuvoton Corporation                                         */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/* File Contents:                                                                    */
/*   i2c_diag.c                                                                      */
/*                                                                                   */
/* This file contains:                                                               */
/*                                                                                   */
/* Project:                                                                          */
/*                                                                                   */
/* Description:                                                                      */
/*   This file is a sample program used to access EEPROM (24LC64) on NUC910         */
/*   EV Board.                                                                       */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. Execute this program on 910 EV board that should set slave addr 0x50 for     */
/*      I2C0 and set slave addr 0x51 for I2C1. It's H/W disign issue.                */
/*   2. Microchip 24LC64 is EEPROM, 64K bits size, page-write buffer for up to       */
/*      32bytes.                                                                     */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/  
 
#include <stdio.h>
#include <string.h>

#include "wblib.h"
#include "i2c.h"


#define CACHE_ON

#define I2CNUM_0	0  
#define I2CNUM_1	1 
#define RETRY		1000  /* ..... Programming cycle may be in progress. Please refer to 24LC64 datasheet */

#define TXSIZE		(1024 * 1)
#define ADDROFFSET  (1024 * 2)

//------------------------- Program -------------------------//
void i2ctestitems(void)
{
	sysprintf("\n");
	sysprintf("+-------------------------------------------------+\n");	
	sysprintf("|            NUC910 I2C Diagnostic Code          |\n");
	sysprintf("+-------------------------------------------------+\n");
	sysprintf("| Channel 0 Byte Write/Random Read          - [1] |\n");
	sysprintf("| Channel 0 Page Write/Sequential Read      - [2] |\n");
	sysprintf("| Channel 1 Byte Write/Random Read          - [3] |\n");
	sysprintf("| Channel 1 Page Write/Sequential Read      - [4] |\n");
	sysprintf("+-------------------------------------------------+\n");	
	sysprintf("| Quit                                    - [ESC] |\n");
	sysprintf("+-------------------------------------------------+\n");
	sysprintf("Select key : \n");
}

void i2ctestitemmsg_1(void)
{
	char ch;
	
	sysprintf("\n\n I2C0 Byte Write/Random Read Test\n\n");
	sysprintf("Description: Write [%d] bytes to 24LC64 EEPROM at offset beginning\n", TXSIZE);
	sysprintf("             address [%d].\n", ADDROFFSET);
	sysprintf("Test   Tool: None.\n");
	sysprintf("Test Result: If data comparison is wrong, program should print the error msg\n");
	sysprintf("             on console. If data is correct, program should print that test\n");
	sysprintf("             success.\n");
	
	sysprintf("\nAny key start test ...\n");
	ch = sysGetChar();
}

void i2ctestitemmsg_2(void)
{
	char ch;
	
	sysprintf("\n\n I2C0 Page Write/Sequential Read Test\n\n");
	sysprintf("Description: Write [%d] bytes to 24LC64 EEPROM at offset beginning\n", TXSIZE);
	sysprintf("             address [%d].\n", ADDROFFSET);
	sysprintf("Test   Tool: None.\n");
	sysprintf("Test Result: If data comparison is wrong, program should print the error msg\n");
	sysprintf("             on console. If data is correct, program should print that test\n");
	sysprintf("             success.\n");
	
	sysprintf("\nAny key start test ...\n");
	ch = sysGetChar();
}

void i2ctestitemmsg_3(void)
{
	char ch;
	
	sysprintf("\n\n I2C1 Byte Write/Random Read Test\n\n");
	sysprintf("Description: Write [%d] bytes to 24LC64 EEPROM at offset beginning\n", TXSIZE);
	sysprintf("             address [%d].\n", ADDROFFSET);
	sysprintf("Test   Tool: None.\n");
	sysprintf("Test Result: If data comparison is wrong, program should print the error msg\n");
	sysprintf("             on console. If data is correct, program should print that test\n");
	sysprintf("             success.\n");
	
	sysprintf("\nAny key start test ...\n");
	ch = sysGetChar();
}

void i2ctestitemmsg_4(void)
{
	char ch;
	
	sysprintf("\n\n I2C1 Page Write/Sequential Read Test\n\n");
	sysprintf("Description: Write [%d] bytes to 24LC64 EEPROM at offset beginning\n", TXSIZE);
	sysprintf("             address [%d].\n", ADDROFFSET);
	sysprintf("Test   Tool: None.\n");
	sysprintf("Test Result: If data comparison is wrong, program should print the error msg\n");
	sysprintf("             on console. If data is correct, program should print that test\n");
	sysprintf("             success.\n");
	
	sysprintf("\nAny key start test ...\n");
	ch = sysGetChar();
}

INT i2c_main(VOID)
{
	unsigned char data[TXSIZE], value[TXSIZE];
	char ch;
	int i, j, err, cnt;
	INT32 rtval;
	
#if 0
	WB_PLL_T sysClock;

	sysClock.pll0 = PLL_200MHZ;
	sysClock.pll1 = PLL_133MHZ;
	sysClock.cpu_src = CPU_FROM_PLL0;
	sysClock.ahb_clk = AHB_CPUCLK_1_2;
	sysClock.apb_clk = APB_AHB_1_2;
	sysSetPLLConfig(&sysClock);
#endif		
	
#ifdef CACHE_ON
	sysDisableCache();
	sysInvalidCache();
	//sysEnableCache(CACHE_WRITE_BACK);  // ..... debug issue
	sysEnableCache(CACHE_WRITE_THROUGH); 	
	sysprintf("Cache on\n");
#endif	
	
	/* initialize test data */
	for(i = 0 ; i < TXSIZE ; i++)
		data[i] = i + 1;
	
	i2cInit();		
	do {
		i2ctestitems();			
		ch = sysGetChar();
		switch(ch)
		{
			case '1':
				/* Channel 0 Byte Write/Random Read */
				i2ctestitemmsg_1();
				rtval = i2cOpen((PVOID)I2CNUM_0);
				if(rtval < 0)
				{
					sysprintf("Open I2C0 error [0x%08x]!\n", rtval);
					break;
				}
				else
					sysprintf("Open I2C0 success\n");
								
				i2cIoctl(I2CNUM_0, I2C_IOC_SET_DEV_ADDRESS, 0x50, 0);  /* On 910 EV board, set 0x50 for I2C0 */
				i2cIoctl(I2CNUM_0, I2C_IOC_SET_SPEED, 100, 0);
				sysprintf("Set I2C0 speed 100KBit/s\n");
				
				/* Tx porcess */
				for(i = 0 ; i < TXSIZE ; i++)
				{
					i2cIoctl(I2CNUM_0, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + i, 2);	
					j = RETRY;	
					while(j-- > 0) 
					{
						if(i2cWrite(I2CNUM_0, &data[i], 1) == 1)
							break;
					}						
					if(j <= 0)
						sysprintf("WRITE ERROR [%d]!\n", i);
					else
						sysprintf("Start TX [%d]\r", i + 1);	
				}
				sysprintf("\n");
				
				/* Rx porcess */	
				memset(value, 0 , TXSIZE);
				for(i = 0 ; i < TXSIZE ; i++)
				{
					i2cIoctl(I2CNUM_0, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + i, 2);	
					j = RETRY;
					while(j-- > 0) 
					{
						if(i2cRead(I2CNUM_0, &value[i], 1) == 1)
							break;
					}
					if(j <= 0)
						sysprintf("Read ERROR [%d]!\n", i);
					else
						sysprintf("Start RX [%d]\r", i + 1);	
				}
				sysprintf("\n");
				
				/* Compare process */
				sysprintf("Compare data\n");
				err = 0;
				cnt = 0;
				for(i = 0 ; i < TXSIZE ; i++)
				{
					if(value[i] != data[i])	
					{
						sysprintf("[%d] addr = 0x%08x, val = 0x%02x (should be 0x%02x)\n", i, i + ADDROFFSET, value[i], data[i]);
						err = 1;
						cnt++;	
						
						#if 0
						/* ..... check error data again */
						vtemp = 0;
						i2cIoctl(I2CNUM_0, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + i, 2);	
						j = RETRY;
						while(j-- > 0) 
						{
							if(i2cRead(I2CNUM_0, &vtemp, 1) == 1)
								break;
						}
						if(j == 0)
							sysprintf("Read ERROR [%d]!\n", i);		
						else
							sysprintf("addr = 0x%08x, val = 0x%02x\n", ADDROFFSET + i, vtemp);	
						#endif	
					}
				}					
				if(err)
					sysprintf("\nTest failed [%d]!\n", cnt);	
				else
					sysprintf("\nTest success\n");	
				
				i2cClose(I2CNUM_0);	
				sysprintf("Close I2C0\n");
				break;
			
			case '2':
				/* Channel 0 Page Write/Sequential Read */
				i2ctestitemmsg_2();				
				rtval = i2cOpen((PVOID)I2CNUM_0);
				if(rtval < 0)
				{
					sysprintf("Open I2C0 error!\n");
					break;
				}		
				else
					sysprintf("Open I2C0 success\n");
						
				i2cIoctl(I2CNUM_0, I2C_IOC_SET_DEV_ADDRESS, 0x50, 0);  /* On 910 EV board, set 0x50 for I2C0 */
				i2cIoctl(I2CNUM_0, I2C_IOC_SET_SPEED, 400, 0);
				sysprintf("Set I2C0 speed 400KBit/s\n");
				
				/* Tx porcess */
				for(i = 0 ; i < (TXSIZE / 32) ; i++)
				{
					i2cIoctl(I2CNUM_0, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + (i*32), 2);	
					j = RETRY;	
					while(j-- > 0) 
					{
						if(i2cWrite(I2CNUM_0, &data[i*32], 32) == 32)
							break;
					}						
					if(j <= 0)
						sysprintf("WRITE ERROR [%d]!\n", i);
					else
						sysprintf("Start TX [%d]\r", (i + 1) * 32);		
				}
				sysprintf("\n");
				
				/* Rx porcess */	
				memset(value, 0 , TXSIZE);
				for(i = 0 ; i < (TXSIZE / 32) ; i++)
				{
					i2cIoctl(I2CNUM_0, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + (i*32), 2);	
					j = RETRY;
					while(j-- > 0) 
					{
						if(i2cRead(I2CNUM_0, &value[i*32], 32) == 32)
							break;
					}
					if(j <= 0)
						sysprintf("Read ERROR [%d]!\n", i);
					else
						sysprintf("Start RX [%d]\r", (i + 1) * 32);		
				}	
				sysprintf("\n");	
				
				/* Compare process */
				sysprintf("Compare data\n");
				err = 0;
				cnt = 0;
				for(i = 0 ; i < TXSIZE ; i++)
				{
					if(value[i] != data[i])	
					{
						sysprintf("[%d] addr = 0x%08x, val = 0x%02x (should be 0x%02x)\n", i, i + ADDROFFSET, value[i], data[i]);
						err = 1;
						cnt++;			
					}
				}					
				if(err)
					sysprintf("\nTest failed [%d]!\n", cnt);	
				else
					sysprintf("\nTest success\n");	
				
				i2cClose(I2CNUM_0);			
				sysprintf("Close I2C0\n");	
				break;	
				
			case '3':
				/* Channel 1 Byte Write/Random Read */
				i2ctestitemmsg_3();
				rtval = i2cOpen((PVOID)I2CNUM_1);
				if(rtval < 0)
				{
					sysprintf("Open I2C1 error!\n");
					break;
				}	
				else
					sysprintf("Open I2C1 success\n");
							
				i2cIoctl(I2CNUM_1, I2C_IOC_SET_DEV_ADDRESS, 0x51, 0);  /* On 910 EV board, set 0x51 for I2C1 */
				i2cIoctl(I2CNUM_1, I2C_IOC_SET_SPEED, 100, 0);
				sysprintf("Set I2C1 speed 100KBit/s\n");
				
				/* Tx porcess */
				for(i = 0 ; i < TXSIZE ; i++)
				{
					i2cIoctl(I2CNUM_1, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + i, 2);	
					j = RETRY;	
					while(j-- > 0) 
					{
						if(i2cWrite(I2CNUM_1, &data[i], 1) == 1)
							break;
					}						
					if(j <= 0)
						sysprintf("WRITE ERROR [%d]!\n", i);
					else
						sysprintf("Start TX [%d]\r", i + 1);		
				}
				sysprintf("\n");
				
				/* Rx porcess */	
				memset(value, 0 , TXSIZE);
				for(i = 0 ; i < TXSIZE ; i++)
				{
					i2cIoctl(I2CNUM_1, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + i, 2);	
					j = RETRY;
					while(j-- > 0) 
					{
						if(i2cRead(I2CNUM_1, &value[i], 1) == 1)
							break;
					}
					if(j <= 0)
						sysprintf("\nRead ERROR [%d]!\n", i);
					else
						sysprintf("Start RX [%d]\r", i + 1);		
				}
				sysprintf("\n");
				
				/* Compare process */
				sysprintf("Compare data\n");
				err = 0;
				cnt = 0;
				for(i = 0 ; i < TXSIZE ; i++)
				{
					if(value[i] != data[i])	
					{
						sysprintf("[%d] addr = 0x%08x, val = 0x%02x (should be 0x%02x)\n", i, i + ADDROFFSET, value[i], data[i]);
						err = 1;
						cnt++;			
					}
				}					
				if(err)
					sysprintf("\nTest failed [%d]!\n", cnt);	
				else
					sysprintf("\nTest success\n");	
				
				i2cClose(I2CNUM_1);		
				sysprintf("Close I2C1\n");			
				break;	
				
			case '4':
				/* Channel 1 Page Write/Sequential Read */
				i2ctestitemmsg_4();
				rtval = i2cOpen((PVOID)I2CNUM_1);
				if(rtval < 0)
				{
					sysprintf("Open I2C1 error!\n");
					break;
				}
				else
					sysprintf("Open I2C1 success\n");
				
				i2cIoctl(I2CNUM_1, I2C_IOC_SET_DEV_ADDRESS, 0x51, 0);  /* On 910 EV board, set 0x51 for I2C1 */
				i2cIoctl(I2CNUM_1, I2C_IOC_SET_SPEED, 400, 0);
				sysprintf("Set I2C1 speed 400KBit/s\n");
				
				/* Tx porcess */
				for(i = 0 ; i < (TXSIZE / 32) ; i++)
				{
					i2cIoctl(I2CNUM_1, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + (i*32), 2);	
					j = RETRY;	
					while(j-- > 0) 
					{
						if(i2cWrite(I2CNUM_1, &data[i*32], 32) == 32)
							break;
					}						
					if(j <= 0)
						sysprintf("WRITE ERROR [%d]!\n", i);
					else
						sysprintf("Start TX [%d]\r", (i + 1) * 32);		
				}
				sysprintf("\n");
				
				/* Rx porcess */	
				memset(value, 0 , TXSIZE);
				for(i = 0 ; i < (TXSIZE / 32) ; i++)
				{
					i2cIoctl(I2CNUM_1, I2C_IOC_SET_SUB_ADDRESS, ADDROFFSET + (i*32), 2);	
					j = RETRY;
					while(j-- > 0) 
					{
						if(i2cRead(I2CNUM_1, &value[i*32], 32) == 32)
							break;
					}
					if(j <= 0)
						sysprintf("Read ERROR [%d]!\n", i);
					else
						sysprintf("Start RX [%d]\r", (i + 1) * 32);		
				}		
				sysprintf("\n");
				
				/* Compare process */
				sysprintf("Compare data\n");
				err = 0;
				cnt = 0;
				for(i = 0 ; i < TXSIZE ; i++)
				{
					if(value[i] != data[i])	
					{
						sysprintf("[%d] addr = 0x%08x, val = 0x%02x (should be 0x%02x)\n", i, i + ADDROFFSET, value[i], data[i]);
						err = 1;
						cnt++;			
					}
				}					
				if(err)
					sysprintf("\nTest failed [%d]!\n", cnt);	
				else
					sysprintf("\nTest success\n");	
				
				i2cClose(I2CNUM_1);	
				sysprintf("Close I2C1\n");										
				break;			
			
			default:
				break;	
		}		
				
	}while(ch != 0x1B);  /* ESC */
		
	i2cExit();	
	return 0;
}	
